package handler

import (
	"strconv"

	"awesomeProject/app/verify"
	"awesomeProject/util"

	"github.com/gin-gonic/gin"

	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/app/service"
)

type UserHandler struct{}

var (
	userSrv service.UserSrv
)

// Login 用户登录
func (r *UserHandler) Login(ctx *gin.Context) {
	var reqFull request.UserLoginWithUsernameFull
	_ = ctx.ShouldBindJSON(&reqFull)

	var req request.UserLoginWithUsername
	//_ = ctx.ShouldBindJSON(&req)
	req.Username = reqFull.Username
	req.Password = reqFull.Password
	// 表单验证
	if err := verify.UserLogin(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}

	// 逻辑处理
	clientIp := reqFull.ClientIp
	//global.LoggerOut(clientIp)
	//global.LoggerOut(reqFull.UserAgent)
	if clientIp == "" {
		clientIp = ctx.Request.URL.Query().Get("client_ip")
	}
	//ip := ctx.ClientIP()
	ip := util.GetClientIP()
	if clientIp == "" {
		clientIp = ip
	}
	//global.LoggerOut(ip)
	userAgent := ctx.Request.UserAgent()
	if reqFull.UserAgent != "" {
		userAgent = reqFull.UserAgent
	}

	response.Result(ctx, userSrv.LoginWithUsername(req.Username, req.Password, clientIp, userAgent))
	return
}

// Logout 注销登录
func (r *UserHandler) Logout(ctx *gin.Context) {
	token := ctx.Request.Header.Get("token")
	response.Result(ctx, userSrv.Logout(token))
	return
}

// Pagination 用户列表（分页）
func (r *UserHandler) Pagination(ctx *gin.Context) {
	var req request.UserPagination
	_ = ctx.Bind(&req)
	// 表单验证
	if err := verify.UserPagination(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}

	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.Pagination(req, user))
	return
}

// Create 用户创建
func (r UserHandler) Create(ctx *gin.Context) {
	// 表单校验
	var req request.UserCreate
	_ = ctx.Bind(&req)
	user := util.CurrentLogin(ctx)
	if err := verify.UserCreate(&req, user); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}
	// 非超管不能创建无组织用户
	if !user.SuperAdmin {
		req.CompanyId = user.CompanyId
	}
	response.Result(ctx, userSrv.Create(model.UserFillAble{
		Username:  req.Username,
		Nickname:  req.Nickname,
		Password:  req.Password,
		CompanyId: req.CompanyId,
	}))
	return
}

// Show 用户详情
func (r UserHandler) Show(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	operator := util.CurrentLogin(ctx)
	user := userSrv.FindByID(uint(id), operator.CompanyId)
	if user.ID == 0 {
		response.Result(ctx, response.ErrRecordNotFound)
		return
	}

	response.Result(ctx, response.OK.WithData(user))
}

func (r UserHandler) UserDetail(ctx *gin.Context) {
	user := util.CurrentLogin(ctx)

	response.Result(ctx, response.OK.WithData(user))
}

// Update 更新用户
func (r *UserHandler) Update(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	var req request.UserUpdate
	_ = ctx.ShouldBindJSON(&req)
	if err := verify.UserUpdate(uint(id), &req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}
	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.Update(uint(id), req, user))
	return
}

func (r *UserHandler) CurrentUpdate(ctx *gin.Context) {
	user := util.CurrentLogin(ctx)
	var req request.CurrentUserUpdate
	_ = ctx.ShouldBindJSON(&req)
	if err := verify.CurrentUserUpdate(user.ID, &req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}
	response.Result(ctx, userSrv.CurrentUpdate(req, user))
	return
}

// PasswordChange 修改密码
func (r *UserHandler) PasswordChange(ctx *gin.Context) {
	var req request.UserPassword
	_ = ctx.Bind(&req)
	if err := verify.UserPassword(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}

	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.PasswordChange(user, req.RPassword, req.Password, req.CPassword))
	return
}

func (r *UserHandler) PasswordReset(ctx *gin.Context) {
	var req request.UserPasswordReset
	_ = ctx.Bind(&req)
	if err := verify.UserPasswordReset(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}

	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.PasswordReset(req.Id, req.NewPassword, user))
	return
}

func (r *UserHandler) UpdateIpLimit(ctx *gin.Context) {
	var req request.UserIpLimit
	_ = ctx.Bind(&req)
	if err := verify.UserIpLimit(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}

	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.UpdateIpLimit(req.Id, req.AllowIp, req.BanIp, user))
	return
}

func (r UserHandler) GetAllLimit(ctx *gin.Context) {
	response.Result(ctx, userSrv.GetAllLimit())
}

func (r *UserHandler) UpdateAllLimit(ctx *gin.Context) {
	var req request.ConfigIpLimitUpdate
	_ = ctx.Bind(&req)
	if err := verify.ConfigIpLimitUpdate(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}

	response.Result(ctx, userSrv.UpdateAllLimit(req.AllowIp, req.BanIp, req.IpRemark))
	return
}

// Menus 获取用户菜单
func (r UserHandler) Menus(ctx *gin.Context) {
	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.Menus(user.ID, user.CompanyId))
	return
}

// Del 删除
func (r UserHandler) Del(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.Del(uint(id), user))
	return
}

// Company 用户所属组织
func (r UserHandler) Company(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	response.Result(ctx, userSrv.Company(uint(id), util.CurrentLogin(ctx)))
	return
}

func (r *UserHandler) UserShops(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	// 店铺权限
	user, _ := ctx.Get("user")
	response.Result(ctx, shopSrv.UserShops(uint(id), user.(model.User)))
	return
}

// AddShopsForUser 用户店铺权限分配
func (r UserHandler) AddShopsForUser(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	var req request.AssignShops
	_ = ctx.Bind(&req)
	if err := verify.AddShopsForUser(&req); err != nil {
		response.Result(ctx, response.ErrInvalidParam.SetMsg(err.Error()))
		return
	}
	user := util.CurrentLogin(ctx)
	response.Result(ctx, userSrv.AddShopsForUser(uint(id), req.ShopIds, user))
	return
}
